﻿#include "CInstanceMgr.h"
#include "../maintask/CTaskMgr.h"
#include "../maintask/CUserTask.h"
#include "../mainctrl.h"
#include "../simpleconfig/CMonsterConfigMgr.h"
#include "../item/CDropItem.h"
#include "../storage/CStorageMgr.h"
#include "commmsg.h"

#include <iostream>
#include <fstream>

#include "pb_cfg_instance.pb.h"
#include "MsgInstance.pb.h"

int CInstanceMgr::LoadConfig(const char* sConfigFile)
{
    int iRet = 0;

    if (sConfigFile == NULL)
    {
        CT_ERROR(("sConfigFile is null"));
        return RET_SYSTEM_FAIL;
    }

    pb_cfg_instance stInstanceCfg;
    std::fstream stFileInput(sConfigFile, std::ios::in | std::ios::binary);
    if (!stInstanceCfg.ParseFromIstream(&stFileInput))
    {
        CT_ERROR(("Failed to Parse stInstanceCfg!"));
        return RET_SYSTEM_FAIL;
    }

    for (int i = 0; i < stInstanceCfg.grade_bonus_rows_size(); ++i)
    {
        const pb_cfg_instance_pb_cfg_grade_bonus_unit & stConfigUnit
            = stInstanceCfg.grade_bonus_rows(i);
            
        CInstanceGradeBonusConfigData stConfigData;
        stConfigData._iBonusID = stConfigUnit.grade_bonus_id();
        
        std::string sTmp;
        const std::string sDel = ",";

        sTmp = stConfigUnit.grade_bonus_need_grade();
        std::vector<std::string> vNeedGrades;
        CTStringUtils::Split(sTmp, sDel, vNeedGrades);

        sTmp = stConfigUnit.grade_bonus_gift_id();
        std::vector<std::string> vGiftIDs;
        CTStringUtils::Split(sTmp, sDel, vGiftIDs);

        if (vNeedGrades.size() != vGiftIDs.size())
        {
            CT_ERROR(("%d", stConfigData._iBonusID));
            return RET_SYS_ERROR;
        }
        
        for (unsigned int i = 0; i < vNeedGrades.size(); ++i)
        {
            CInstanceGradeBonusConfigDetail stConfigDetail;
            stConfigDetail._usGiftConfigID = (unsigned short)atoi(vGiftIDs[i].c_str());
            stConfigDetail._usNeedGrade = (unsigned short)atoi(vNeedGrades[i].c_str());
        
            stConfigData._astGradeConfigs.AddOneItem(stConfigDetail);
        }

        iRet = _stInstanceGradeBonusConfig.AddConfig(stConfigData);
        CHECK_RETURN(iRet);
    }

    for (int i = 0; i < stInstanceCfg.first_bonus_rows_size(); ++i)
    {
        const pb_cfg_instance_pb_cfg_first_bonus_unit & stFirstBonusPbCfgUnit
            = stInstanceCfg.first_bonus_rows(i);

        CInstanceFirstAccomplishBonusConfigData stConfigData;
        stConfigData._uiBonusID = (unsigned int)(stFirstBonusPbCfgUnit.bonus_id() & 0x7FFFFFFF);

        CInstanceDropSingleItem stDropItemData;

        stDropItemData._ucItemType = (unsigned char)(stFirstBonusPbCfgUnit.item_type1() & 0x7F);
        if (stDropItemData._ucItemType == ITEM_TYPE_NULL)
        {
            continue;
        }
        stDropItemData._uiItemID = (unsigned int)(stFirstBonusPbCfgUnit.item_id1() & 0x7FFFFFFF);
        stDropItemData._usItemCount = (unsigned short)(stFirstBonusPbCfgUnit.item_count1() & 0x7FFF);
        stConfigData._astDropItems.AddOneItem(stDropItemData);

        stDropItemData._ucItemType = (unsigned char)(stFirstBonusPbCfgUnit.item_type2() & 0x7F);
        if (stDropItemData._ucItemType == ITEM_TYPE_NULL)
        {
            continue;
        }
        stDropItemData._uiItemID = (unsigned int)(stFirstBonusPbCfgUnit.item_id2() & 0x7FFFFFFF);
        stDropItemData._usItemCount = (unsigned short)(stFirstBonusPbCfgUnit.item_count2() & 0x7FFF);
        stConfigData._astDropItems.AddOneItem(stDropItemData);

        stDropItemData._ucItemType = (unsigned char)(stFirstBonusPbCfgUnit.item_type3() & 0x7F);
        if (stDropItemData._ucItemType == ITEM_TYPE_NULL)
        {
            continue;
        }
        stDropItemData._uiItemID = (unsigned int)(stFirstBonusPbCfgUnit.item_id3() & 0x7FFFFFFF);
        stDropItemData._usItemCount = (unsigned short)(stFirstBonusPbCfgUnit.item_count3() & 0x7FFF);
        stConfigData._astDropItems.AddOneItem(stDropItemData);

        stDropItemData._ucItemType = (unsigned char)(stFirstBonusPbCfgUnit.item_type4() & 0x7F);
        if (stDropItemData._ucItemType == ITEM_TYPE_NULL)
        {
            continue;
        }
        stDropItemData._uiItemID = (unsigned int)(stFirstBonusPbCfgUnit.item_id4() & 0x7FFFFFFF);
        stDropItemData._usItemCount = (unsigned short)(stFirstBonusPbCfgUnit.item_count4() & 0x7FFF);
        stConfigData._astDropItems.AddOneItem(stDropItemData);

        stDropItemData._ucItemType = (unsigned char)(stFirstBonusPbCfgUnit.item_type5() & 0x7F);
        if (stDropItemData._ucItemType == ITEM_TYPE_NULL)
        {
            continue;
        }
        stDropItemData._uiItemID = (unsigned int)(stFirstBonusPbCfgUnit.item_id5() & 0x7FFFFFFF);
        stDropItemData._usItemCount = (unsigned short)(stFirstBonusPbCfgUnit.item_count5() & 0x7FFF);
        stConfigData._astDropItems.AddOneItem(stDropItemData);

        stDropItemData._ucItemType = (unsigned char)(stFirstBonusPbCfgUnit.item_type6() & 0x7F);
        if (stDropItemData._ucItemType == ITEM_TYPE_NULL)
        {
            continue;
        }
        stDropItemData._uiItemID = (unsigned int)(stFirstBonusPbCfgUnit.item_id6() & 0x7FFFFFFF);
        stDropItemData._usItemCount = (unsigned short)(stFirstBonusPbCfgUnit.item_count6() & 0x7FFF);
        stConfigData._astDropItems.AddOneItem(stDropItemData);

        iRet = _stFirstAccomplishBonusConfig.AddConfig(stConfigData);
        CHECK_RETURN(iRet);
    }

    for (int i = 0; i < stInstanceCfg.instance_list_rows_size(); ++i)
    {
        const pb_cfg_instance_pb_cfg_instance_list_unit & stInstanceListPbCfgUnit
            = stInstanceCfg.instance_list_rows(i);

        CInstanceConfigData stConfigData;
        stConfigData._ucInstanceType = (unsigned char)(stInstanceListPbCfgUnit.type_id() & 0x7F);
        stConfigData._usInstanceID = (unsigned short)(stInstanceListPbCfgUnit.instance_id() & 0x7FFF);
        stConfigData._usOpenLevel = (unsigned short)(stInstanceListPbCfgUnit.open_level() & 0x7FFF);
        stConfigData._iRelatedTaskID = stInstanceListPbCfgUnit.open_task_id();
        stConfigData._ucUseEnergy = (unsigned char)(stInstanceListPbCfgUnit.use_energy() & 0x7F);

        //怪物等级
        std::string sMonsterGroupLevel = stInstanceListPbCfgUnit.level();
        const std::string sDel = ",";
        std::vector<std::string> vMonsterGroupLevels;
        CTStringUtils::Split(sMonsterGroupLevel, sDel, vMonsterGroupLevels);
        stConfigData._astMonsterGroupLevels.m_iUsedCount = stConfigData._astMonsterGroupLevels.GetCount();

        if ((int)vMonsterGroupLevels.size() > stConfigData._astMonsterGroupLevels.GetCount())
        {
            CT_ERROR((""));
            return RET_SYS_ERROR;
        }

        for (unsigned int j = 0; j < vMonsterGroupLevels.size(); ++j)
        {
            stConfigData._astMonsterGroupLevels[j] = atoi(vMonsterGroupLevels[j].c_str());
        }

        iRet = _stInstanceGradeBonusConfig.AddIncludeInstance(stInstanceListPbCfgUnit.grade_bonus_id(), stInstanceListPbCfgUnit.instance_id());
        CHECK_RETURN(iRet);

        unsigned int uiMonsterGroupID;
        uiMonsterGroupID = (unsigned int)(stInstanceListPbCfgUnit.monster_group_id1() & 0x7FFFFFFF);
        if (uiMonsterGroupID != 0)
        {
            stConfigData._astMonsterGroupIDs.AddOneItem(uiMonsterGroupID);
            stConfigData._astMonsterGroupPos.AddOneItem(1);
        }

        uiMonsterGroupID = (unsigned int)(stInstanceListPbCfgUnit.monster_group_id2() & 0x7FFFFFFF);
        if (uiMonsterGroupID != 0)
        {
            stConfigData._astMonsterGroupIDs.AddOneItem(uiMonsterGroupID);
            stConfigData._astMonsterGroupPos.AddOneItem(2);
        }

        uiMonsterGroupID = (unsigned int)(stInstanceListPbCfgUnit.monster_group_id3() & 0x7FFFFFFF);
        if (uiMonsterGroupID != 0)
        {
            stConfigData._astMonsterGroupIDs.AddOneItem(uiMonsterGroupID);
            stConfigData._astMonsterGroupPos.AddOneItem(3);
        }

        uiMonsterGroupID = (unsigned int)(stInstanceListPbCfgUnit.monster_group_id4() & 0x7FFFFFFF);
        if (uiMonsterGroupID != 0)
        {
            stConfigData._astMonsterGroupIDs.AddOneItem(uiMonsterGroupID);
            stConfigData._astMonsterGroupPos.AddOneItem(4);
        }

        uiMonsterGroupID = (unsigned int)(stInstanceListPbCfgUnit.monster_group_id5() & 0x7FFFFFFF);
        if (uiMonsterGroupID != 0)
        {
            stConfigData._astMonsterGroupIDs.AddOneItem(uiMonsterGroupID);
            stConfigData._astMonsterGroupPos.AddOneItem(5);
        }

        //检查怪物等级
        for (int j = 0; j < stConfigData._astMonsterGroupIDs.Size(); ++j)
        {
            if (stConfigData._astMonsterGroupLevels.Size() <= j 
                || stConfigData._astMonsterGroupLevels[j] == 0)
            {
                CT_ERROR(("instance %d monster level error", stConfigData._usInstanceID));
                return RET_SYS_ERROR;
            }
        }

        unsigned char ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.normal_drop_item_type1() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.normal_drop_item_id1();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.normal_drop_item_subtype1().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.normal_drop_item_rate1() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.normal_drop_item_count1();

            stConfigData._astNormalDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.normal_drop_item_type2() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.normal_drop_item_id2();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.normal_drop_item_subtype2().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.normal_drop_item_rate2() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.normal_drop_item_count2();

            stConfigData._astNormalDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.normal_drop_item_type3() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.normal_drop_item_id3();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.normal_drop_item_subtype3().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.normal_drop_item_rate3() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.normal_drop_item_count3();

            stConfigData._astNormalDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.normal_drop_item_type4() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.normal_drop_item_id4();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.normal_drop_item_subtype4().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.normal_drop_item_rate4() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.normal_drop_item_count4();

            stConfigData._astNormalDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.normal_drop_item_type5() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.normal_drop_item_id5();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.normal_drop_item_subtype5().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.normal_drop_item_rate5() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.normal_drop_item_count5();

            stConfigData._astNormalDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.boss_drop_item_type1() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.boss_drop_item_id1();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.boss_drop_item_subtype1().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.boss_drop_item_rate1() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.boss_drop_item_count1();

            stConfigData._astBossDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.boss_drop_item_type2() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.boss_drop_item_id2();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.boss_drop_item_subtype2().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.boss_drop_item_rate2() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.boss_drop_item_count2();

            stConfigData._astBossDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.boss_drop_item_type3() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.boss_drop_item_id3();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.boss_drop_item_subtype3().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.boss_drop_item_rate3() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.boss_drop_item_count3();

            stConfigData._astBossDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.boss_drop_item_type4() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.boss_drop_item_id4();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.boss_drop_item_subtype4().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.boss_drop_item_rate4() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.boss_drop_item_count4();

            stConfigData._astBossDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.boss_drop_item_type5() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.boss_drop_item_id5();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.boss_drop_item_subtype5().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.boss_drop_item_rate5() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.boss_drop_item_count5();

            stConfigData._astBossDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.instance_drop_item_type1() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.instance_drop_item_id1();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.instance_drop_item_subtype1().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.instance_drop_item_rate1() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.instance_drop_item_count1();

            stConfigData._astInstanceDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.instance_drop_item_type2() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.instance_drop_item_id2();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.instance_drop_item_subtype2().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.instance_drop_item_rate2() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.instance_drop_item_count2();

            stConfigData._astInstanceDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.instance_drop_item_type3() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.instance_drop_item_id3();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.instance_drop_item_subtype3().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.instance_drop_item_rate3() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.instance_drop_item_count3();

            stConfigData._astInstanceDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.instance_drop_item_type4() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.instance_drop_item_id4();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.instance_drop_item_subtype4().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.instance_drop_item_rate4() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.instance_drop_item_count4();

            stConfigData._astInstanceDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.instance_drop_item_type5() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.instance_drop_item_id5();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.instance_drop_item_subtype5().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.instance_drop_item_rate5() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.instance_drop_item_count5();

            stConfigData._astInstanceDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        ucDropItemType = (unsigned char)(stInstanceListPbCfgUnit.instance_drop_item_type6() & 0x7F);
        if (ucDropItemType != ITEM_TYPE_NULL)
        {
            CInstanceDropItemConfigData stDropItemConfigData;
            stDropItemConfigData._ucDropItemType = ucDropItemType;
            stDropItemConfigData._usDropItemConfigID = stInstanceListPbCfgUnit.instance_drop_item_id6();
            stDropItemConfigData._szDropItemSubType.Set("%s", stInstanceListPbCfgUnit.instance_drop_item_subtype6().c_str());
            stDropItemConfigData._uiDropRate = (unsigned int)(stInstanceListPbCfgUnit.instance_drop_item_rate6() & 0x7FFFFFFF);
            stDropItemConfigData._iDropCount = stInstanceListPbCfgUnit.instance_drop_item_count6();

            stConfigData._astInstanceDropItemGroup.AddOneItem(stDropItemConfigData);
        }

        unsigned int uiFirstBonusID = stInstanceListPbCfgUnit.first_bonus_id();
        if (uiFirstBonusID != 0)
        {
            CInstanceFirstAccomplishBonusConfigData stBonusConfigData;
            iRet = _stFirstAccomplishBonusConfig.GetConfig(uiFirstBonusID, stBonusConfigData);
            CHECK_RETURN(iRet);
            stConfigData._stFirstBonus = stBonusConfigData;
        }

        stConfigData._bHasSpecialBonus = stInstanceListPbCfgUnit.has_special_bonus() != 0;

        iRet = AddConfigData(stConfigData);
        CHECK_RETURN(iRet);

        iRet = CMainCtrl::m_pstMain->m_stItemMgr.AddInstanceDropConfig(stConfigData);
        CHECK_RETURN(iRet);
    }

    for (int i = 0; i < stInstanceCfg.secret_config_rows_size(); ++i)
    {
        const pb_cfg_instance_pb_cfg_secret_config_unit & stInstancePbCfgUnit
            = stInstanceCfg.secret_config_rows(i);

        CSecretInstanceConfigData stConfigData;
        stConfigData._ucSecretID = stInstancePbCfgUnit.secret_id();
        stConfigData._usOpenLevel = stInstancePbCfgUnit.open_level();
        stConfigData._ucInstanceType = stInstancePbCfgUnit.ins_type();
        stConfigData._ucInstanceCount = stInstancePbCfgUnit.ins_count();
        stConfigData._ucHardSecretType = stInstancePbCfgUnit.hard_ins_type();
        stConfigData._uiDropBoxID = stInstancePbCfgUnit.drop_box_id();
        stConfigData._uiShowBoxID = stInstancePbCfgUnit.show_box_id();

        iRet = _stSecretInstanceConfig.AddConfig(stConfigData);
        CHECK_RETURN(iRet);
    }

    CBattleScoreConfigData stBSConfigData;
    for (int i = 0; i < stInstanceCfg.battle_score_config_rows_size(); ++i)
    {
        const pb_cfg_instance_pb_cfg_battle_score_config_unit & stBattleScorePbCfgUnit
            = stInstanceCfg.battle_score_config_rows(i);

        stBSConfigData.Clear();

        stBSConfigData.SetResID(stBattleScorePbCfgUnit.res_id());
        stBSConfigData.SetAttackScore(stBattleScorePbCfgUnit.attack_score());
        stBSConfigData.SetAttackGrid(stBattleScorePbCfgUnit.attack_grid());
        stBSConfigData.SetDefendScore(stBattleScorePbCfgUnit.defend_score());
        stBSConfigData.SetDefendGrid(stBattleScorePbCfgUnit.defend_grid());
        stBSConfigData.SetMarkStar(stBattleScorePbCfgUnit.mark_star());

        iRet = _stBattleScoreConfig.AddConfig(stBSConfigData);
        CHECK_RETURN(iRet);
    }

    return 0;
}

int CInstanceMgr::FlushStat(CUserInstance& stUserInstance, CUserTask& stUserTask)
{
    int iRet = 0;

    iRet = FlushStat(stUserInstance, stUserTask, CInstanceConfigData::INSTANCE_TYPE_MAIN);
    CHECK_RETURN(iRet);

    iRet = FlushStat(stUserInstance, stUserTask, CInstanceConfigData::INSTANCE_TYPE_CHALLENGE);
    CHECK_RETURN(iRet);

    for (int i = CInstanceConfigData::INSTANCE_TYPE_CHALLENGE + 1;
        i <= CInstanceConfigData::INSTANCE_TYPE_MAX; ++i)
    {
        if (!_stInstanceConfig.HasConfig(i))
        {
            continue;
        }

        iRet = FlushStat(stUserInstance, stUserTask, i);
        CHECK_RETURN(iRet);
    }

    return 0;
}

int CInstanceMgr::FlushStat(CUserInstance& stUserInstance, CUserTask& stUserTask,
                            unsigned char ucInstanceType)
{
    int iRet = 0;

    if (ucInstanceType < CInstanceConfigData::INSTANCE_TYPE_MIN || ucInstanceType > CInstanceConfigData::INSTANCE_TYPE_MAX)
    {
        return ERROR_INSTANCE_TYPE;
    }

    //获取等级
    int iIndex = CMainCtrl::m_pstMain->m_stPlayerSnsCommInfoHash.HashFind(stUserTask.GetUserGid());
    if (iIndex < 0)
    {
        CT_ERROR(("%u", stUserTask.GetUserGid()));
        return RET_SYS_ERROR;
    }
    unsigned short usLevel = CMainCtrl::m_pstMain->m_stPlayerSnsCommInfoHash[iIndex]._usLevel;

    if (CInstanceConfigData::IsSecret(ucInstanceType)) //秘境需要先做等级检查，再做从普通到困难难度的检查
    {
        //检查所有秘境
        for (unsigned char i = 1; i <= MAX_INSTANCE_SECRET_CONFIG_COUNT; ++i)
        {
            if (!_stSecretInstanceConfig.IsValidSecretInstanceId(i))
            {
                break;
            }

            CSecretInstanceConfigData stSecretConfigData;
            iRet = _stSecretInstanceConfig.GetConfig(i, stSecretConfigData);
            if (iRet)
            {
                CT_WARNING(("%d, %d", i, iRet));
                break;
            }            

            if (stSecretConfigData._ucInstanceType != ucInstanceType
                || stSecretConfigData._ucHardSecretType == 0)
            {
                continue;
            }

            CSecretInstanceConfigData stHardSecretConfigData;
            iRet = _stSecretInstanceConfig.GetConfig(stSecretConfigData._ucHardSecretType, stHardSecretConfigData);
            if (RET_OK != iRet)
            {
                CT_WARNING((""));
                break;
            }

            unsigned short usNowInstanceAccTo = 0;
            GetFinishedStat(stUserInstance, ucInstanceType, usNowInstanceAccTo);

            unsigned short usNowHardInstanceAccTo = 0;
            GetFinishedStat(stUserInstance, stHardSecretConfigData._ucInstanceType, usNowHardInstanceAccTo);

            if (usNowInstanceAccTo >= stSecretConfigData._ucInstanceCount
                && usNowHardInstanceAccTo == 0)   //已经通关
            {
                SetOpened(stUserInstance, stHardSecretConfigData._ucInstanceType, 1);
            }
        }
    }

    unsigned short usMaxInstanceID = 0;
    unsigned short usInstanceID = 0;
    switch(ucInstanceType)
    {
    case CInstanceConfigData::INSTANCE_TYPE_MAIN:
        usInstanceID = stUserInstance._stInstanceData._stHasOpenedInstanceData._usMainInstanceData;
        usMaxInstanceID = stUserInstance._stInstanceData._stHasFinishedInstanceData._usMainInstanceData + 1;
        break;
    case CInstanceConfigData::INSTANCE_TYPE_CHALLENGE:
        usInstanceID = stUserInstance._stInstanceData._stHasOpenedInstanceData._usChallengeInstanceData;
        usMaxInstanceID =  stUserInstance._stInstanceData._stHasFinishedInstanceData._usChallengeInstanceData + 1;
        break;
    default:
        {
            int iIndex = ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE;
            if (iIndex >= stUserInstance._stInstanceData._stHasOpenedInstanceData._aucBranchInstances.Size())
            {
                usInstanceID = 0;
                usMaxInstanceID = 1;
            }
            else
            {
                usInstanceID = stUserInstance._stInstanceData._stHasOpenedInstanceData._aucBranchInstances[iIndex];
                usMaxInstanceID = stUserInstance._stInstanceData._stHasFinishedInstanceData._aucBranchInstances[iIndex] + 1;
            }
        }
        
        break;
    }

    //更新状态，查看后续副本是否可以打开
    while (usInstanceID < usMaxInstanceID)
    {
        CInstanceDetailStatData stInstanceDetailStatData;
        iRet = GetInstanceDetailStat(stUserInstance, ucInstanceType, stInstanceDetailStatData);
        if (iRet != 0)
        {
            break;
        }

        CInstanceConfigData stNextInstanceConfigData;
        unsigned short usNextInstanceID = usInstanceID + 1;
        if (GetConfigData(ucInstanceType, usNextInstanceID, stNextInstanceConfigData) != 0)
        {
            break;
        }

        CInstanceConfigData stNowInstanceConfigData;

        if (usInstanceID != 0)
        {
            if (GetConfigData(ucInstanceType, usInstanceID, stNowInstanceConfigData) != 0)
            {
                break;
            }
        }

        CTaskID stTaskID;
        stTaskID._uiTaskID = stNextInstanceConfigData._iRelatedTaskID % TASK_CONFIG_ID_MOD;
        stTaskID._uiBranchID = stNextInstanceConfigData._iRelatedTaskID / TASK_CONFIG_ID_MOD;

        if ( usLevel >= stNextInstanceConfigData._usOpenLevel
            &&(CMainCtrl::m_pstMain->m_stTaskMgr.IsTaskFinished(stUserTask, stTaskID) || CMainCtrl::m_pstMain->m_stTaskMgr.IsTaskAccepted(stUserTask, stTaskID))
            && (usInstanceID == 0 || stInstanceDetailStatData.ucNowAccomplishPos >= stNowInstanceConfigData._astMonsterGroupIDs.Size()))
        {
            SetOpened(stUserInstance, ucInstanceType, usNextInstanceID);
            usInstanceID = usNextInstanceID;
        }
        else
        {
            break;
        }
    }

    return 0;
}

int CInstanceMgr::GetOpenStat(CUserInstance& stUserInstance, CUserTask& stUserTask,
                                unsigned char ucInstanceType, unsigned short& usInstanceID)
{
    int iRet = 0;

    if (ucInstanceType < CInstanceConfigData::INSTANCE_TYPE_MIN || ucInstanceType > CInstanceConfigData::INSTANCE_TYPE_MAX)
    {
        return ERROR_INSTANCE_TYPE;
    }

    iRet = FlushStat(stUserInstance, stUserTask, ucInstanceType);
    CHECK_RETURN(iRet);

    switch(ucInstanceType)
    {
    case CInstanceConfigData::INSTANCE_TYPE_MAIN:
        usInstanceID = stUserInstance._stInstanceData._stHasOpenedInstanceData._usMainInstanceData;
        break;
    case CInstanceConfigData::INSTANCE_TYPE_CHALLENGE:
        usInstanceID = stUserInstance._stInstanceData._stHasOpenedInstanceData._usChallengeInstanceData;
        break;
    default:
        {
            int iIndex = ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE;
            if (iIndex >= stUserInstance._stInstanceData._stHasOpenedInstanceData._aucBranchInstances.Size())
            {
                usInstanceID = 0;
            }
            else
            {
                usInstanceID = stUserInstance._stInstanceData._stHasOpenedInstanceData._aucBranchInstances[iIndex];
            }
        }
        
        break;
    }

    return 0;
}

int CInstanceMgr::GetFinishedStat(CUserInstance& stUserInstance, unsigned char ucInstanceType, unsigned short& usInstanceID)
{
    if (ucInstanceType < CInstanceConfigData::INSTANCE_TYPE_MIN || ucInstanceType > CInstanceConfigData::INSTANCE_TYPE_MAX)
    {
        return ERROR_INSTANCE_TYPE;
    }

    switch(ucInstanceType)
    {
    case CInstanceConfigData::INSTANCE_TYPE_MAIN:
        usInstanceID = stUserInstance._stInstanceData._stHasFinishedInstanceData._usMainInstanceData;
        break;
    case CInstanceConfigData::INSTANCE_TYPE_CHALLENGE:
        usInstanceID = stUserInstance._stInstanceData._stHasFinishedInstanceData._usChallengeInstanceData;
        break;
    default:
        {
            GetBranceInstId (stUserInstance._stInstanceData._stHasFinishedInstanceData, ucInstanceType, usInstanceID);
        }
        
        break;
    }

    return 0;
}

void CInstanceMgr::GetBranceInstId (CInstanceStatData & stInstanceData, unsigned char ucInstanceType, unsigned short& usInstanceID)
{
    int iIndex = ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE;
    if (iIndex >= stInstanceData._aucBranchInstances.Size())
    {
        usInstanceID = 0;
    }
    else
    {
        usInstanceID = stInstanceData._aucBranchInstances[iIndex];
    }
}


int CInstanceMgr::IsCanSweep(CUserInstance& stUserInstance, unsigned char ucInstanceType, unsigned short usInstanceID)
{
    int iRet = 0;
    unsigned short usFinishInstanceID = 0xFFF;
    iRet = GetFinishedStat(stUserInstance, ucInstanceType, usFinishInstanceID);
    CHECK_RETURN(iRet);

    if (usInstanceID <= usFinishInstanceID)
    {
        return RET_OK;
    }
    else if (usInstanceID == usFinishInstanceID + 1)
    {
        return ERROR_INSTANCE_CAN_NOT_SWEEP2;
    }
    else
    {
        return ERROR_INSTANCE_CAN_NOT_SWEEP3;
    }
}

int CInstanceMgr::SetOpened(CUserInstance& stUserInstance, unsigned char ucInstanceType, unsigned short usInstanceID)
{
    if (ucInstanceType < CInstanceConfigData::INSTANCE_TYPE_MIN || ucInstanceType > CInstanceConfigData::INSTANCE_TYPE_MAX)
    {
        return ERROR_INSTANCE_TYPE;
    }

    bool bNeedClearStat = false;
    switch(ucInstanceType)
    {
    case CInstanceConfigData::INSTANCE_TYPE_MAIN:
        {
            if (usInstanceID >= MAX_INSTANCE_MAIN_CONFIG_COUNT)
            {
                return ERROR_INSTANCE_ID;
            }

            if (stUserInstance._stInstanceData._stHasOpenedInstanceData._usMainInstanceData < usInstanceID)
            {
                stUserInstance._stInstanceData._stHasOpenedInstanceData._usMainInstanceData = usInstanceID;
                bNeedClearStat = true;
            }
        }
        break;
    case CInstanceConfigData::INSTANCE_TYPE_CHALLENGE:
        {
            if (usInstanceID >= MAX_INSTANCE_CHALLENGE_CONFIG_COUNT)
            {
                return ERROR_INSTANCE_ID;
            }

            if (stUserInstance._stInstanceData._stHasOpenedInstanceData._usChallengeInstanceData < usInstanceID)
            {
                stUserInstance._stInstanceData._stHasOpenedInstanceData._usChallengeInstanceData = usInstanceID;
                bNeedClearStat = true;
            }
        }
        break;
    default:
        {
            if (usInstanceID >= MAX_INSTANCE_BRANCH_CONFIG_COUNT)
            {
                return ERROR_INSTANCE_ID;
            }

            int iIndex = ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE;
            while (iIndex >= stUserInstance._stInstanceData._stHasOpenedInstanceData._aucBranchInstances.Size())
            {
                stUserInstance._stInstanceData._stHasOpenedInstanceData._aucBranchInstances.AddOneItem(0);
            }

            if (stUserInstance._stInstanceData._stHasOpenedInstanceData._aucBranchInstances[ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE] < usInstanceID)
            {
                stUserInstance._stInstanceData._stHasOpenedInstanceData._aucBranchInstances[ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE] = usInstanceID;
                bNeedClearStat = true;
            }
        }
        break;
    }

    if (bNeedClearStat)
    {
        //清理副本战斗详细数据
        CInstanceDetailStatData stInstanceDetailStat;
        SetInstanceDetailStat(stUserInstance, ucInstanceType, stInstanceDetailStat);
    }

    return 0;
}

int CInstanceMgr::SetFinished(CUserInstance& stUserInstance, unsigned char ucInstanceType, unsigned short usInstanceID)
{
    if (ucInstanceType < CInstanceConfigData::INSTANCE_TYPE_MIN || ucInstanceType > CInstanceConfigData::INSTANCE_TYPE_MAX)
    {
        return ERROR_INSTANCE_TYPE;
    }

    switch(ucInstanceType)
    {
    case CInstanceConfigData::INSTANCE_TYPE_MAIN:
        {
            if (usInstanceID >= MAX_INSTANCE_MAIN_CONFIG_COUNT)
            {
                return ERROR_INSTANCE_ID;
            }

            if (stUserInstance._stInstanceData._stHasOpenedInstanceData._usMainInstanceData < usInstanceID)
            {
                return ERROR_INSTANCE_ID;
            }

            stUserInstance._stInstanceData._stHasFinishedInstanceData._usMainInstanceData =
                    CT_MAX(usInstanceID, stUserInstance._stInstanceData._stHasFinishedInstanceData._usMainInstanceData);
        }
        break;
    case CInstanceConfigData::INSTANCE_TYPE_CHALLENGE:
        {
            if (usInstanceID >= MAX_INSTANCE_CHALLENGE_CONFIG_COUNT)
            {
                return ERROR_INSTANCE_ID;
            }

            if (stUserInstance._stInstanceData._stHasOpenedInstanceData._usChallengeInstanceData < usInstanceID)
            {
                return ERROR_INSTANCE_ID;
            }

            stUserInstance._stInstanceData._stHasFinishedInstanceData._usChallengeInstanceData =
                    CT_MAX(usInstanceID, stUserInstance._stInstanceData._stHasFinishedInstanceData._usChallengeInstanceData);
        }
        break;
    default:
        {
            if (usInstanceID >= MAX_INSTANCE_BRANCH_CONFIG_COUNT)
            {
                return ERROR_INSTANCE_ID;
            }

            int iIndex = ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE;
            while (iIndex >= stUserInstance._stInstanceData._stHasFinishedInstanceData._aucBranchInstances.Size())
            {
                stUserInstance._stInstanceData._stHasFinishedInstanceData._aucBranchInstances.AddOneItem(0);
            }

            if (stUserInstance._stInstanceData._stHasOpenedInstanceData._aucBranchInstances[ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE] < usInstanceID)
            {
                return ERROR_INSTANCE_ID;
            }

            stUserInstance._stInstanceData._stHasFinishedInstanceData._aucBranchInstances[ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE] =
                    CT_MAX(usInstanceID, stUserInstance._stInstanceData._stHasFinishedInstanceData._aucBranchInstances[ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE]);
        }
        break;
    }

    return 0;
}

bool CInstanceMgr::IsCanInto(CUserInstance& stUserInstance, CUserTask& stUserTask,
                          unsigned char ucInstanceType, unsigned short usInstanceID)
{
    int iRet = 0;
    unsigned short usOpenedMaxInstance;
    iRet = GetOpenStat(stUserInstance, stUserTask, ucInstanceType, usOpenedMaxInstance);
    if (iRet != 0)
    {
        return false;
    }

    return usInstanceID <= usOpenedMaxInstance;
}

bool CInstanceMgr::IsFinished(CUserInstance& stUserInstance, unsigned char ucInstanceType, unsigned short usInstanceID)
{
    int iRet = 0;
    unsigned short usFinishedMaxInstance;
    iRet = GetFinishedStat(stUserInstance, ucInstanceType, usFinishedMaxInstance);
    if (iRet != 0)
    {
        return false;
    }

    return usInstanceID <= usFinishedMaxInstance;
}

int CInstanceMgr::GoIntoInstance(CUserInstance& stUserInstance, CUserTask& stUserTask,
                unsigned char ucInstanceType, unsigned short usInstanceID)
{
    if (!IsCanInto(stUserInstance, stUserTask, ucInstanceType, usInstanceID))
    {
        return ERROR_INSTANCE_CAN_NOT_INTO_SCENE;
    }

    //检查精力
    if (ucInstanceType == CInstanceConfigData::INSTANCE_TYPE_MAIN
        || CInstanceConfigData::IsElite(ucInstanceType)
        || CInstanceConfigData::IsSecret(ucInstanceType))
    {
        int iIndex = CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash.HashFind(stUserTask.GetUserGid());
        if (iIndex < 0)
        {
            CT_ERROR(("%u", stUserTask.GetUserGid()));
            return RET_SYS_ERROR;
        }
        
        int iNowEnergy = CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash[iIndex]._stUserEnergy.GetEnergy(CMainCtrl::m_pstMain->m_iNow);
    
        CInstanceConfigData stConfigData;
        _stInstanceConfig.GetConfigData(ucInstanceType, usInstanceID, stConfigData);

        if (iNowEnergy < 0 || iNowEnergy < stConfigData._ucUseEnergy)
        {
            return ERROR_INSTANCE_NO_ENERGY; 
        }
    }
    stUserInstance._ucNowAtInstanceType = ucInstanceType;
    stUserInstance._usNowAtInstanceID = usInstanceID;
    stUserInstance._usNowPos = 0;
    stUserInstance._bHasGetInsWinBonus = true;
    stUserInstance._bHasGetSecWinBonus = true;
    stUserInstance._ucSecretID = 0;
    stUserInstance._stScore.Clear();

    return 0;
}

int CInstanceMgr::GoIntoSecret(CUserInstance& stUserInstance, CUserTask& stUserTask, unsigned char ucSecID)
{
    int iRet = 0;
    
    CSecretInstanceConfigData stSecretConfigData;
    iRet = _stSecretInstanceConfig.GetConfig(ucSecID, stSecretConfigData);
    CHECK_RETURN(iRet);

    //获取当前打到哪个副本
    unsigned short usMaxAtkInstanceID = stUserInstance._stInstanceData._stSecretInstanceData.GetMaxAtkInstanceID(ucSecID, CMainCtrl::m_pstMain->m_iNow);
    if (usMaxAtkInstanceID >= (unsigned short)stSecretConfigData._ucInstanceCount)
    {
        return ERROR_INSTANCE_SECRET_HAS_FINISHED;
    }

    //进入副本
    iRet = GoIntoInstance(stUserInstance, stUserTask, stSecretConfigData._ucInstanceType, usMaxAtkInstanceID + 1);
    CHECK_RETURN(iRet);

    //设置数据
    stUserInstance._ucSecretID = ucSecID;

    return 0;
}

int CInstanceMgr::LeaveInstance(CUserInstance& stUserInstance)
{
    stUserInstance._ucNowAtInstanceType = 0;
    stUserInstance._usNowAtInstanceID = 0;
    stUserInstance._usNowPos = 0;
    stUserInstance._bHasGetInsWinBonus = true;

    return 0;
}

int CInstanceMgr::GetMonsterGroupList(CUserInstance& stUserInstance, T_INSTANCE_MONSTER_GROUP_IDS& astMonsterGroupIDs)
{
    int iRet = 0;

    if (stUserInstance._usNowAtInstanceID == 0)
    {
        return ERROR_INSTANCE_NOT_IN_INSTANCE;
    }

    CInstanceConfigData stConfigData;
    iRet = GetConfigData(stUserInstance._ucNowAtInstanceType, stUserInstance._usNowAtInstanceID, stConfigData);
    CHECK_RETURN(iRet);

    astMonsterGroupIDs = stConfigData._astMonsterGroupIDs;
    return 0;
}

int CInstanceMgr::AttackMonsterGroup(CUserInstance& stUserInstance, CMonsterGroupConfigData& stConfigData)
{
    int iRet = 0;

    if (stUserInstance._usNowAtInstanceID == 0)
    {
        return ERROR_INSTANCE_NOT_IN_INSTANCE;
    }

    CInstanceConfigData stInstanceConfigData;
    iRet = GetConfigData(stUserInstance._ucNowAtInstanceType, stUserInstance._usNowAtInstanceID, stInstanceConfigData);
    CHECK_RETURN(iRet);

    if (stUserInstance._usNowPos >= stInstanceConfigData._astMonsterGroupIDs.Size())
    {
        return ERROR_INSTANCE_IS_ACCOMPLISH;
    }

    unsigned int iMonsterGroupID = stInstanceConfigData._astMonsterGroupIDs[stUserInstance._usNowPos];
    unsigned short usMonsterGroupLevel = stInstanceConfigData._astMonsterGroupLevels[stUserInstance._usNowPos];
    iRet = CMainCtrl::m_pstMain->m_stMonsterConfigMgr.GetMonsterGroupConfig(iMonsterGroupID, usMonsterGroupLevel, stConfigData);
    CHECK_RETURN(iRet);

    return 0;
}

int CInstanceMgr::AttackMonsterGroupWin(unsigned int uiGID, CUserInstance& stUserInstance, CDropItem& stDropItem)
{
    int iRet = 0;

    CDropItemData stDropItemData;

    if (stUserInstance._usNowAtInstanceID == 0)
    {
        return ERROR_INSTANCE_NOT_IN_INSTANCE;
    }

    CInstanceConfigData stInstanceConfigData;
    iRet = GetConfigData(stUserInstance._ucNowAtInstanceType, stUserInstance._usNowAtInstanceID, stInstanceConfigData);
    CHECK_RETURN(iRet);

    if (stUserInstance._usNowPos >= stInstanceConfigData._astMonsterGroupIDs.Size())
    {
        return ERROR_INSTANCE_IS_ACCOMPLISH;
    }

    unsigned int iMonsterGroupID = stInstanceConfigData._astMonsterGroupIDs[stUserInstance._usNowPos];
    unsigned short usMonsterGroupLevel = stInstanceConfigData._astMonsterGroupLevels[stUserInstance._usNowPos];

    CMonsterGroupConfigData stMonsterGroupConfigData;
    iRet = CMainCtrl::m_pstMain->m_stMonsterConfigMgr.GetMonsterGroupConfig(iMonsterGroupID, stMonsterGroupConfigData);
    CHECK_RETURN(iRet);

    CInstanceDetailStatData stDetailStatData;
    iRet = GetInstanceDetailStat(stUserInstance, stUserInstance._ucNowAtInstanceType, stDetailStatData);
    CHECK_RETURN(iRet);

    //发放战胜怪物的基础奖励
    stDropItem.SetOssModule(OSS_MODULE_MONSTER);
    CInstanceConfigData::T_DROP_ITEM_GROUP_CONFIG& stDropItemGroupConfig = 
        (stMonsterGroupConfigData._ucIsBoss == 1 ? stInstanceConfigData._astBossDropItemGroup : stInstanceConfigData._astNormalDropItemGroup);
    //发放 stDropItemGroupConfig中的内容
    for (int i = 0; i < stDropItemGroupConfig.Size(); ++i)
    {
        stDropItemData.Clear();
        if (0 == stDropItemGroupConfig[i]._usDropItemConfigID)
        {
            CMainCtrl::m_pstMain->m_stItemMgr.GetDropItemData(uiGID, stDropItemGroupConfig[i]._ucDropItemType,
                                                            0,
                                                            stDropItemGroupConfig[i]._szDropItemSubType(),
                                                            stDropItemGroupConfig[i]._uiDropRate,
                                                            stDropItemGroupConfig[i]._iDropCount,
                                                            stDropItemData);
        }
        else
        {
            CMainCtrl::m_pstMain->m_stItemMgr.GetDropItemData(uiGID, stDropItemGroupConfig[i]._ucDropItemType,
                                                            stDropItemGroupConfig[i]._usDropItemConfigID,
                                                            "",
                                                            stDropItemGroupConfig[i]._uiDropRate,
                                                            stDropItemGroupConfig[i]._iDropCount,
                                                            stDropItemData);
        }

        stDropItem.Drop(stDropItemData);
    }

    //发放击杀怪物奖励
    CMonsterKillBonusConfigData stMonsterKillBonusConfigData;
    iRet = CMainCtrl::m_pstMain->m_stMonsterConfigMgr.GetMonsterKillBonusConfig(usMonsterGroupLevel, stMonsterKillBonusConfigData);
    CHECK_RETURN(iRet);

    // 发放stMonsterKillBonusConfigData中的奖励
    CMainCtrl::m_pstMain->m_stItemMgr.GetDropItemData(uiGID, ITEM_TYPE_EXP, 0, "", COMM_MOD, (int)stMonsterKillBonusConfigData._uiExp, stDropItemData);
    stDropItem.Drop(stDropItemData);
    CMainCtrl::m_pstMain->m_stItemMgr.GetDropItemData(uiGID, ITEM_TYPE_SILVER, 0, "", COMM_MOD, (int)stMonsterKillBonusConfigData._uiSilver, stDropItemData);
    stDropItem.Drop(stDropItemData);
    CMainCtrl::m_pstMain->m_stItemMgr.GetDropItemData(uiGID, ITEM_TYPE_LILIAN, 0, "", COMM_MOD, (int)stMonsterKillBonusConfigData._uiLilian, stDropItemData);
    stDropItem.Drop(stDropItemData);

    //发放首次击杀怪物奖励
    if (stMonsterGroupConfigData._bHasFirstKillBonus
        && !IsFinished(stUserInstance, stUserInstance._ucNowAtInstanceType, stUserInstance._usNowAtInstanceID)
        && (unsigned short)stDetailStatData.ucNowAccomplishPos <= stUserInstance._usNowPos)
    {
        CMonsterFirstKillBonusConfigData stMonsterFirstKillBonusConfigData;
        iRet = CMainCtrl::m_pstMain->m_stMonsterConfigMgr.GetMonsterFirstKillBonusConfig(usMonsterGroupLevel, stMonsterFirstKillBonusConfigData);
        CHECK_RETURN(iRet);

        //发放stMonsterFirstKillBonusConfigData中的奖励
        CMainCtrl::m_pstMain->m_stItemMgr.GetDropItemData(uiGID, ITEM_TYPE_HUNLI, 0, "", COMM_MOD, (int)stMonsterFirstKillBonusConfigData._uiHunli, 
                                                stDropItemData);
        stDropItem.Drop(stDropItemData);
    }

    //扣除精力
    if ((stUserInstance._ucNowAtInstanceType == CInstanceConfigData::INSTANCE_TYPE_MAIN
        || CInstanceConfigData::IsElite(stUserInstance._ucNowAtInstanceType)
        || CInstanceConfigData::IsSecret(stUserInstance._ucNowAtInstanceType))
        && stUserInstance._usNowPos == 0)
    {
        int iIndex = CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash.HashFind(uiGID);
        if (iIndex < 0)
        {
            CT_ERROR(("%u", uiGID));
            return RET_SYS_ERROR;
        }
        
        CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash[iIndex]._stUserEnergy.SubEnergy(stInstanceConfigData._ucUseEnergy, CMainCtrl::m_pstMain->m_iNow);
        CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(uiGID, NOTIFY_ROLE_INFO);
    }

    //设置状态
    stUserInstance._usNowPos += 1;
    if (!IsFinished(stUserInstance, stUserInstance._ucNowAtInstanceType, stUserInstance._usNowAtInstanceID)
        && (unsigned short)stDetailStatData.ucNowAccomplishPos < stUserInstance._usNowPos)
    {
        stDetailStatData.ucNowAccomplishPos = stUserInstance._usNowPos & 0x7F;
        SetInstanceDetailStat(stUserInstance, stUserInstance._ucNowAtInstanceType, stDetailStatData);
    }

    //博物馆副本数据更新
    if (CInstanceConfigData::IsMuseum(stUserInstance._ucNowAtInstanceType))
    {
        int iIndex = CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash.HashFind(uiGID);
        if (iIndex < 0)
        {
            CT_WARNING(("%u", uiGID));
            return 0;
        }
        CUserTask& stUserTask = CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash[iIndex]._stUserTask;

        //增加攻击雕像次数
        stUserInstance._stInstanceData._stMuseumInstanceData._iTotalAtkCount += 1;

        //检查排行榜
        CInstanceMuseumRankData stRankData;
        stRankData._uiGID = uiGID;
        stRankData._iAtkCount = stUserInstance._stInstanceData._stMuseumInstanceData._iTotalAtkCount;
        GetOpenStat(stUserInstance, stUserTask, stUserInstance._ucNowAtInstanceType, stRankData._usMaxInstanceID);

        CInstanceDetailStatData stDetailStatData;
        GetInstanceDetailStat(stUserInstance, stUserInstance._ucNowAtInstanceType, stDetailStatData);
        stRankData._ucMaxEnemyPos = stDetailStatData.ucNowAccomplishPos;

        int iNewRank = 0;
        int iOldRank = 0;
        _stMuseumRank.Update(stRankData, iOldRank, iNewRank);

        if (iOldRank != iNewRank    //排名有变化
            || iNewRank != -1)      //排名中的数值有变化
        {
            UpdateZoneData(); //更新数据
        }
    }

    return 0;
}

int CInstanceMgr::AttackInstanceWin(unsigned int uiGID, CUserInstance& stUserInstance, CDropItem& stDropItem)
{
    int iRet = 0;
    int iNowTime = CMainCtrl::m_pstMain->m_iNow;

    if (stUserInstance._usNowAtInstanceID == 0)
    {
        return ERROR_INSTANCE_NOT_IN_INSTANCE;
    }

    CInstanceConfigData stInstanceConfigData;
    iRet = GetConfigData(stUserInstance._ucNowAtInstanceType, stUserInstance._usNowAtInstanceID, stInstanceConfigData);
    CHECK_RETURN(iRet);

    if (stUserInstance._usNowPos < stInstanceConfigData._astMonsterGroupIDs.Size())
    {
        return ERROR_INSTANCE_IS_NOT_ACCOMPLISH;
    }

    CInstanceDetailStatData stDetailStatData;
    iRet = GetInstanceDetailStat(stUserInstance, stUserInstance._ucNowAtInstanceType, stDetailStatData);
    CHECK_RETURN(iRet);

    CDropItemData stDropItemData;
    CInstanceConfigData::T_DROP_ITEM_GROUP_CONFIG& stFinishDropItemGroupConfig = stInstanceConfigData._astInstanceDropItemGroup;
    //掉落 stFinishDropItemGroupConfig中的内容，需要掉落到场景里
    stDropItem.SetOssModule(OSS_MODULE_INSTANCE);
    for (int i = 0; i < stFinishDropItemGroupConfig.Size(); ++i)
    {
        if (0 == stFinishDropItemGroupConfig[i]._usDropItemConfigID)
        {
            CMainCtrl::m_pstMain->m_stItemMgr.GetDropItemData(uiGID, stFinishDropItemGroupConfig[i]._ucDropItemType,
                                                            0,
                                                            stFinishDropItemGroupConfig[i]._szDropItemSubType(),
                                                            stFinishDropItemGroupConfig[i]._uiDropRate,
                                                            stFinishDropItemGroupConfig[i]._iDropCount,
                                                            stDropItemData);
        }
        else
        {
            CMainCtrl::m_pstMain->m_stItemMgr.GetDropItemData(uiGID, stFinishDropItemGroupConfig[i]._ucDropItemType,
                                                            stFinishDropItemGroupConfig[i]._usDropItemConfigID,
                                                            "",
                                                            stFinishDropItemGroupConfig[i]._uiDropRate,
                                                            stFinishDropItemGroupConfig[i]._iDropCount,
                                                            stDropItemData);
        }

        stDropItem.Drop(stDropItemData);

        //发放家族奖励
        if (ITEM_TYPE_SILVER == stDropItemData._ucItemType
            || ITEM_TYPE_EXP == stDropItemData._ucItemType)
        {   
            CDropItemData stClanBonus;            
            iRet = CMainCtrl::m_pstMain->m_stClanMgr.GetClanInsBonus (uiGID, stDropItemData._ucItemType, stDropItemData._iItemCount, stClanBonus);
            if(0 == iRet)      
            { 
                stDropItem.Drop(stClanBonus);
            }
        }
    }

    //发放首次通关奖励
    if (!IsFinished(stUserInstance, stUserInstance._ucNowAtInstanceType, stUserInstance._usNowAtInstanceID))
    {
        //掉落stInstanceConfigData._stFirstBonus中的奖励
        for (int i = 0; i < stInstanceConfigData._stFirstBonus._astDropItems.Size(); ++i)
        {
            CInstanceDropSingleItem& stDropSingleItem = stInstanceConfigData._stFirstBonus._astDropItems[i];
            CMainCtrl::m_pstMain->m_stItemMgr.GetDropItemData(uiGID, stDropSingleItem._ucItemType,
                stDropSingleItem._uiItemID,
                "",
                COMM_MOD,
                (int)stDropSingleItem._usItemCount,
                stDropItemData);
            stDropItem.Drop(stDropItemData);
        }
    }

    //发放特殊奖励
    if (stInstanceConfigData._bHasSpecialBonus)
    {
        //todo: 发放特殊奖励
    }    

    //设置状态
    if (!IsFinished(stUserInstance, stUserInstance._ucNowAtInstanceType, stUserInstance._usNowAtInstanceID))
    {
        SetFinished(stUserInstance, stUserInstance._ucNowAtInstanceType, stUserInstance._usNowAtInstanceID);
    }

    //保存评分
    switch (stUserInstance._ucNowAtInstanceType)
    {
    case CInstanceConfigData::INSTANCE_TYPE_MAIN:
        stUserInstance._stInstanceData._stMainInstanceGrad.SetGrad(stUserInstance._usNowAtInstanceID, stUserInstance._stScore.GetGrade());
        break;
    default:
        break;
    }

    if (CInstanceConfigData::IsElite(stUserInstance._ucNowAtInstanceType))
    {
        //评分
        stUserInstance._stInstanceData.SetEliteGrade(stUserInstance._ucNowAtInstanceType - CInstanceConfigData::INSTANCE_TYPE_ELITE_BEGIN, 
                            stUserInstance._usNowAtInstanceID, stUserInstance._stScore.GetGrade());
        
        //通关次数
        stUserInstance._stInstanceData._stEliteAtkStat.AtkWin(stUserInstance._ucNowAtInstanceType - CInstanceConfigData::INSTANCE_TYPE_ELITE_BEGIN, stUserInstance._usNowAtInstanceID, iNowTime);
    }

    if (CInstanceConfigData::IsSecret(stUserInstance._ucNowAtInstanceType))
    {
        //评分
        CSecretInstanceConfigData stSecretConfigData;
        iRet = _stSecretInstanceConfig.GetConfig(stUserInstance._ucSecretID, stSecretConfigData);
        if (RET_OK == iRet && stUserInstance._usNowAtInstanceID >= stSecretConfigData._ucInstanceCount) //通关后才需要记录评分
        {
            stUserInstance._stInstanceData._stSecretInstanceData._stGrade.SetGrad(stUserInstance._ucSecretID, stUserInstance._stScore.GetGrade());
        }

        //设置通关次数
        stUserInstance._stInstanceData._stSecretInstanceData.AtkWin(stUserInstance._ucSecretID, 
                                                stUserInstance._usNowAtInstanceID, iNowTime);
    }

    return 0;
}

bool CInstanceMgr::IsInstanceWin(CUserInstance& stUserInstance)
{
    if (stUserInstance._ucNowAtInstanceType < CInstanceConfigData::INSTANCE_TYPE_MIN
        || stUserInstance._ucNowAtInstanceType > CInstanceConfigData::INSTANCE_TYPE_MAX)
    {
        return false;
    }

    if (stUserInstance._usNowAtInstanceID == 0)
    {
        return false;
    }

    CInstanceConfigData stInstanceConfigData;
    int iRet = GetConfigData(stUserInstance._ucNowAtInstanceType, stUserInstance._usNowAtInstanceID, stInstanceConfigData);
    if (iRet != 0)
    {
        return false;
    }

    return stUserInstance._usNowPos >= stInstanceConfigData._astMonsterGroupIDs.Size();
}

void CInstanceMgr::KillEnemyTriggerTask(CUserTask& stUserTask, CMonsterGroupConfigData& stMonsterGroupConfigData)
{
    //获取怪物数量
    CTLib::CTArray<CTaskCond, MAX_MONSTER_MEMBER_PER_GROUP> astTaskConds;
    for (int i = 0; i < stMonsterGroupConfigData._astMonsters.Size(); ++i)
    {
        CMonsterGroupMember& stMonster = stMonsterGroupConfigData._astMonsters[i];
        int j = 0;
        for (; j < astTaskConds.Size(); ++j)
        {
            if (astTaskConds[j]._iCondData1 == (int)stMonster._uiMonsterID)
            {
                astTaskConds[j]._iCondData2 += 1;
                break;
            }
        }

        if (j == astTaskConds.Size())
        {
            astTaskConds.AddOneItem(CTaskCond());
            astTaskConds[astTaskConds.Size() - 1]._iCondData1 = stMonster._uiMonsterID;
            astTaskConds[astTaskConds.Size() - 1]._iCondData2 = 1;
        }
    }

    //触发
    for (int i = 0; i < astTaskConds.Size(); ++i)
    {
        CMainCtrl::m_pstMain->m_stTaskMgr.TriggerKillEnemy(stUserTask, astTaskConds[i]._iCondData1, astTaskConds[i]._iCondData2);
    }
}

int CInstanceMgr::GetInstanceDetailStat(CUserInstance& stUserInstance, unsigned char ucInstanceType, CInstanceDetailStatData& stDetailStatData)
{
    if (ucInstanceType < CInstanceConfigData::INSTANCE_TYPE_MIN
        || ucInstanceType > CInstanceConfigData::INSTANCE_TYPE_MAX)
    {
        return ERROR_INSTANCE_TYPE;
    }

    switch(ucInstanceType)
    {
    case CInstanceConfigData::INSTANCE_TYPE_MAIN:
        stDetailStatData = stUserInstance._stInstanceData._stMainDetailStat;
        break;
    case CInstanceConfigData::INSTANCE_TYPE_CHALLENGE:
        stDetailStatData = stUserInstance._stInstanceData._stChallengeDetailStat;
        break;
    default:
        {
            int iIndex = ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE;
            if (iIndex >= stUserInstance._stInstanceData._astBranchDetailStat.Size())
            {
                stDetailStatData = CInstanceDetailStatData();
            }
            else
            {
                stDetailStatData = stUserInstance._stInstanceData._astBranchDetailStat[iIndex];
            }
        }
        
        break;
    }

    return 0;
}

int CInstanceMgr::SetInstanceDetailStat(CUserInstance& stUserInstance, unsigned char ucInstanceType, CInstanceDetailStatData& stDetailStatData)
{
    if (ucInstanceType < CInstanceConfigData::INSTANCE_TYPE_MIN
        || ucInstanceType > CInstanceConfigData::INSTANCE_TYPE_MAX)
    {
        return ERROR_INSTANCE_TYPE;
    }

    switch(ucInstanceType)
    {
    case CInstanceConfigData::INSTANCE_TYPE_MAIN:
        stUserInstance._stInstanceData._stMainDetailStat = stDetailStatData;
        break;
    case CInstanceConfigData::INSTANCE_TYPE_CHALLENGE:
        stUserInstance._stInstanceData._stChallengeDetailStat = stDetailStatData;
        break;
    default:
        {
            int iIndex = ucInstanceType - CInstanceConfigData::INSTANCE_TYPE_CHALLENGE;
            while (iIndex >= stUserInstance._stInstanceData._astBranchDetailStat.Size())
            {
                stUserInstance._stInstanceData._astBranchDetailStat.AddOneItem(CInstanceDetailStatData());
            }
            stUserInstance._stInstanceData._astBranchDetailStat[iIndex] = stDetailStatData;
        }
        break;
    }

    return 0;
}
#if 0
//获取物品的掉落关卡
//查找规则: 如果查找的结果中能找到多个副本,按如下规则返回结果. 如果找不到,返回item表中配置的缺省关卡
//1. 副本类型。 (主线 > 挑战)   2.可以打开的还是未打开的？ (打开>未打开)
//3. 掉落类型。 (指定ID >指定了字符串)  4.查找到得掉落类型. (普通掉落>副本掉落)  6.往前\往后只找五个
int CInstanceMgr::CheckInstanceDrop (unsigned char ucInstanceType, unsigned short usInstanceID, unsigned char ucDropItemType,
                                     unsigned short usItemID, CDropItemSubTypeConfigData::T_DROP_ITEM_SUBTYPE_CONFIG_KEY szKey)
{
    CInstanceConfigData stConfigData;
    int iRet = GetConfigData(ucInstanceType, usInstanceID, stConfigData);
    CHECK_RETURN(iRet);

    for (int i = 0; i < stConfigData._astNormalDropItemGroup.Size(); i++)
    {
        if (((usItemID == stConfigData._astNormalDropItemGroup[i]._usDropItemConfigID)
            && (ucDropItemType == stConfigData._astNormalDropItemGroup[i]._ucDropItemType))
            ||((ucDropItemType == stConfigData._astNormalDropItemGroup[i]._ucDropItemType)
              && (0 != stConfigData._astNormalDropItemGroup[i]._iDropCount)
              && (0 != stConfigData._astNormalDropItemGroup[i]._uiDropRate)
              && (szKey == stConfigData._astNormalDropItemGroup[i]._szDropItemSubType)))
        {
            return 0;
        }
    }

    for (int i = 0; i < stConfigData._astInstanceDropItemGroup.Size(); i++)
    {
        if (((usItemID == stConfigData._astNormalDropItemGroup[i]._usDropItemConfigID)
            && (ucDropItemType == stConfigData._astNormalDropItemGroup[i]._ucDropItemType))
            ||((ucDropItemType == stConfigData._astInstanceDropItemGroup[i]._ucDropItemType)            
               && (0 != stConfigData._astInstanceDropItemGroup[i]._iDropCount)
               && (0 != stConfigData._astInstanceDropItemGroup[i]._uiDropRate)
               && (szKey == stConfigData._astInstanceDropItemGroup[i]._szDropItemSubType)))
        {
            return 0;
        }
    }
    //获取物品的掉落字符串
    CDropItemSubTypeConfigData::T_DROP_ITEM_SUBTYPE_CONFIG_KEY szKey;

    int iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetItemDropType (ucItemType, usItemID, szKey);
    CHECK_RETURN(iRet);

    //往前查找,直到第一个副本
    usInstanceID = stCurStat._usChallengeInstanceData;
    ucInstanceType = CInstanceConfigData::INSTANCE_TYPE_CHALLENGE;
    for (int i = 0; i < 5; i++)
    {
        iRet = CheckInstanceDrop(ucInstanceType, usInstanceID, ucItemType, usItemID, szKey);
        if (0 == iRet)
        {    
            stDropInstanceId._ucInstanceType = ucInstanceType;
            stDropInstanceId._usInstanceID = usInstanceID;

            return 0;
        }

        usInstanceID -= 1;
    }

    //往后查找,直到最后一个副本
    usInstanceID = stCurStat._usChallengeInstanceData;
    for (int i = 0; i < 5; i++)
    {
        iRet = CheckInstanceDrop(ucInstanceType, usInstanceID, ucItemType, usItemID, szKey);
        if (0 == iRet)
        {    
            stDropInstanceId._ucInstanceType = ucInstanceType;
            stDropInstanceId._usInstanceID = usInstanceID;

            return 0;
        }

        usInstanceID += 1;
    }

    if (iRet)
    {
        CT_ERROR(("INSTANCE: Get item drop instance id failed. ucItemType: %u, usItemID: %u, CurMain: %u, CurChall: %u",
            ucItemType, usItemID, stCurStat._usMainInstanceData, stCurStat._usChallengeInstanceData));
    }
    else
    {
        CT_TRACE(("INSTANCE: Get item drop instance id ok. ucItemType: %u, usItemID: %u, drop instance (type: %u, id: %u)",
            ucItemType, usItemID, stDropInstanceId._ucInstanceType, stDropInstanceId._usInstanceID));
    }


    return -1;
}
#endif

int CInstanceMgr::GetDropInstanceID(unsigned char ucItemType, unsigned short usItemId, CInstanceStatData & stCurStat, CInstanceId & stDropId)
{
    stDropId.Clear();

    CMainCtrl * pstMainCtrl = CMainCtrl::m_pstMain;

    CDropInstanceConfig stDropInstances;
    int iRet = pstMainCtrl->m_stItemMgr.GetItemDropInstance (ucItemType, usItemId, stDropInstances);
    if (iRet)
    {
        CT_ERROR(("%d, %d, %d", ucItemType, usItemId, iRet));
        return iRet;
    }

    //1. 副本类型。 (主线 > 挑战 > 秘境)
    CInstanceId stCurInstId;
    stCurInstId._ucInstanceType = CInstanceConfigData::INSTANCE_TYPE_MAIN;
    stCurInstId._usInstanceID = stCurStat._usMainInstanceData; 
    bool bHasFindInst = pstMainCtrl->m_stItemMgr.FindItemDropInstance (stDropInstances, stCurInstId, stDropId);
    if (bHasFindInst)
    {
        return RET_OK;
    }


    //精英副本
    for (unsigned char i = CInstanceConfigData::INSTANCE_TYPE_ELITE_BEGIN; i < CInstanceConfigData::INSTANCE_TYPE_ELITE_END; ++i)
    {
        if (!CInstanceConfigData::IsElite(i))
        {
            continue;
        }

        stCurInstId._ucInstanceType = i;
        GetBranceInstId (stCurStat, i, stCurInstId._usInstanceID);
        bHasFindInst = pstMainCtrl->m_stItemMgr.FindItemDropInstance (stDropInstances, stCurInstId, stDropId);
        if (bHasFindInst)
        {
            return RET_OK;
        }
    }


    //秘境副本
    for (unsigned char i = CInstanceConfigData::INSTANCE_TYPE_SECRET_BEGIN; i < CInstanceConfigData::INSTANCE_TYPE_SECRET_END; ++i)
    {
        if (!CInstanceConfigData::IsSecret(i))
        {
            continue;
        }

        stCurInstId._ucInstanceType = i;
        GetBranceInstId (stCurStat, i, stCurInstId._usInstanceID);
        bHasFindInst = pstMainCtrl->m_stItemMgr.FindItemDropInstance (stDropInstances, stCurInstId, stDropId);
        if (bHasFindInst)
        {
            return RET_OK;
        }
    }

    return ERROR_INSTANCE_CANNOT_DROP_ITEM;
}

int CInstanceMgr::GetSuitableMonster(CUserInstance& stUserInstance, unsigned int& uiMonsterID, unsigned short& usMonsterInInsID)
{
    int iRet = 0;
    const int MAX_FIND_COUNT = 100;
    CTArray<uint64, MAX_FIND_COUNT> _astMonsterID; //这里面的ID可能重复

    unsigned short usInstanceID = 0;
    unsigned char ucInstanceType = CInstanceConfigData::INSTANCE_TYPE_MAIN;
    GetFinishedStat(stUserInstance, ucInstanceType, usInstanceID);
    unsigned short usMinInstanceID = CT_MAX((int)usInstanceID - 10, 1);
    
    while (usInstanceID >= usMinInstanceID && _astMonsterID.Size() < _astMonsterID.GetCount())
    {
        CInstanceConfigData stInstanceConfigData;
        iRet = _stInstanceConfig.GetConfigData(ucInstanceType, usInstanceID, stInstanceConfigData);
        if (iRet != 0)
        {
            continue;
        }

        for (int i = 0; i < stInstanceConfigData._astMonsterGroupIDs.Size(); ++i)
        {
            unsigned int uiMonsterGroupID = stInstanceConfigData._astMonsterGroupIDs[i];

            CMonsterGroupConfigData stMonsterGroupConfigData;
            iRet = CMainCtrl::m_pstMain->m_stMonsterConfigMgr.GetMonsterGroupConfig(uiMonsterGroupID, stMonsterGroupConfigData);
            if (iRet != 0)
            {
                continue;
            }

            for (int j = 0; j < stMonsterGroupConfigData._astMonsters.Size(); ++j)
            {
                _astMonsterID.AddOneItem(CT_UINT64_MAKE(usInstanceID, stMonsterGroupConfigData._astMonsters[j]._uiMonsterID));
            }
        }

        usInstanceID--;
    }
    
    if (_astMonsterID.Size() == 0)
    {
        return ERROR_INSTANCE_NO_SUITABLE_MONSTER;
    }

    int iIndex = CT_RANDOM_NUM->GetRand(_astMonsterID.Size());
    usMonsterInInsID = (unsigned short)CT_UINT64_HIGH(_astMonsterID[iIndex]);
    uiMonsterID = CT_UINT64_LOW(_astMonsterID[iIndex]);
    
    return 0;
}

int CInstanceMgr::GetSuitableItem(CUserInstance& stUserInstance, unsigned char ucItemType, unsigned short& usItemConfigID, unsigned short& usItemInInsID)
{
    int iRet = 0;
    const int MAX_FIND_COUNT = 100;
    CTArray<unsigned int, MAX_FIND_COUNT> astItemConfigIDs; //这里面的ID可能重复

    unsigned short usInstanceID = stUserInstance._stInstanceData._stHasFinishedInstanceData._usMainInstanceData;
    unsigned short usMinInstanceID = CT_MAX((int)usInstanceID - 10, 1);
    unsigned char ucInstanceType = CInstanceConfigData::INSTANCE_TYPE_MAIN;

    while (usInstanceID >= usMinInstanceID && astItemConfigIDs.Size() < astItemConfigIDs.GetCount())
    {
        CInstanceConfigData stInstanceConfigData;
        iRet = _stInstanceConfig.GetConfigData(ucInstanceType, usInstanceID, stInstanceConfigData);
        if (iRet != 0)
        {
            continue;
        }

        CInstanceConfigData::T_ALL_DROP_ITEM_CONFIG_ID astConfigIDs;
        GetAllInstanceDropItem(stInstanceConfigData._astNormalDropItemGroup, ucItemType, astConfigIDs);
        GetAllInstanceDropItem(stInstanceConfigData._astBossDropItemGroup, ucItemType, astConfigIDs);
        GetAllInstanceDropItem(stInstanceConfigData._astInstanceDropItemGroup, ucItemType, astConfigIDs);

        for (int i = 0; i < astConfigIDs.Size() && astItemConfigIDs.Size() < astItemConfigIDs.GetCount(); ++i)
        {
            astItemConfigIDs.AddOneItem(CT_UINT_MAKE(usInstanceID, astConfigIDs[i]));
        }

        usInstanceID--;
    }

    if (astItemConfigIDs.Size() > 0)
    {
        int iIndex = CT_RANDOM_NUM->GetRand(astItemConfigIDs.Size());
        usItemInInsID = CT_UINT_HIGH(astItemConfigIDs[iIndex]);
        usItemConfigID = CT_UINT_LOW(astItemConfigIDs[iIndex]);
    }
    else
    {
        usItemConfigID = 0;
    }
    
    return 0;
}   

void CInstanceMgr::GetAllInstanceDropItem(CInstanceConfigData::T_DROP_ITEM_GROUP_CONFIG& astDropGroup, unsigned char ucItemType,
                                          CInstanceConfigData::T_ALL_DROP_ITEM_CONFIG_ID& astConfigIDs)
{
    for (int i = 0; i < astDropGroup.Size(); ++i)
    {
        if (ucItemType != astDropGroup[i]._ucDropItemType)
        {
            continue;
        }

        if (astDropGroup[i]._szDropItemSubType.GetDataLen() > 0)  //掉落串
        {
            CDropItemSubTypeConfig::T_DROP_ITEM_SUBTYPE_CONFIG_DATA astData;
            switch (ucItemType)
            {
            case ITEM_TYPE_EQUIP:
                CMainCtrl::m_pstMain->m_stEquipMgr._stEquipConfig._stDropItemSubTypeConfig.GetAllSubTypeItem(astDropGroup[i]._szDropItemSubType, astData);
                break;
            case ITEM_TYPE_SCROLL:
                CMainCtrl::m_pstMain->m_stItemMgr._stScrollConfig._stDropItemSubTypeConfig.GetAllSubTypeItem(astDropGroup[i]._szDropItemSubType, astData);
                break;
            case ITEM_TYPE_MATERIAL:
                CMainCtrl::m_pstMain->m_stItemMgr._stMaterialConfig._stDropItemSubTypeConfig.GetAllSubTypeItem(astDropGroup[i]._szDropItemSubType, astData);
                break;
            case ITEM_TYPE_CRYSTAL:
                CMainCtrl::m_pstMain->m_stItemMgr._stCrystalConfig._stDropItemSubTypeConfig.GetAllSubTypeItem(astDropGroup[i]._szDropItemSubType, astData);
                break;
            default:
                break;
            }

            for (int j = 0; j < astData.Size(); ++j)
            {
                astConfigIDs.AddOneItem((unsigned short)astData[j]._iItemID);
            }
        }
        else
        {
            astConfigIDs.AddOneItem(astDropGroup[i]._usDropItemConfigID);  //指定配置ID
        }
    }
    
}

void CInstanceMgr::SendInstanceInfoToFront(CUserInstance& stUserInstance, CUserTask& stUserTask, PBMsgHead stMsgHead, CEnpNetHead stEnpHead)
{
    MsgAnsGetInstanceInfo stAns;
    stMsgHead.set_msgid(ID_MAIN_GET_INSTANCE_INFO);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
    unsigned short usInstanceID = 0;

    for (int i = CInstanceConfigData::INSTANCE_TYPE_MIN; i <= CInstanceConfigData::INSTANCE_TYPE_MAX; ++i)
    {
        if (CInstanceConfigData::IsSecret(i)) //秘境用自己的协议返回数据
        {
            continue;
        }

        MsgInstanceInfo* pstInstanceInfo = stAns.add_infos();
        pstInstanceInfo->set_type(i);

        GetOpenStat(stUserInstance, stUserTask, i, usInstanceID);
        pstInstanceInfo->set_open_to(usInstanceID);

        GetFinishedStat(stUserInstance, i, usInstanceID);
        pstInstanceInfo->set_acc_to(usInstanceID);

        CInstanceDetailStatData stDetailStatData;
        GetInstanceDetailStat(stUserInstance, i, stDetailStatData);
        pstInstanceInfo->set_enemy_to(stDetailStatData.ucNowAccomplishPos);
    }

    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();
    CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
    CMainCtrl::m_pstMain->EncodePBMsg(stAns, CMainCtrl::m_pstMain->m_stEncodeBuf);

    CMainCtrl::m_pstMain->AnswerToClient(stEnpHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
}

void CInstanceMgr::SendInstanceGradeToFront(CUserInstance& stUserInstance, CUserTask& stUserTask, PBMsgHead stMsgHead, CEnpNetHead stEnpHead)
{
    MsgAnsInstanceDetail stAns;
    stMsgHead.set_msgid(ID_MAIN_INS_DETAIL_INFO);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    //主线副本
    unsigned char ucInstanceType = CInstanceConfigData::INSTANCE_TYPE_MAIN;
    unsigned short usInstanceAccTo = 0;
    GetFinishedStat(stUserInstance, ucInstanceType, usInstanceAccTo);
    MsgInstanceGrade* pstInstanceGrade = stAns.add_grade();
    pstInstanceGrade->set_ins_type(ucInstanceType);

    for (unsigned short i = 1; i <= usInstanceAccTo; ++i)
    {
        unsigned char ucGrade = 0;
        stUserInstance._stInstanceData._stMainInstanceGrad.GetGrad(i, ucGrade);
        pstInstanceGrade->add_data(ucGrade);
    }

    //精英副本
    for (unsigned char i = CInstanceConfigData::INSTANCE_TYPE_ELITE_BEGIN; 
                i < CInstanceConfigData::INSTANCE_TYPE_ELITE_END; ++i)
    {
        if (CInstanceConfigData::IsElite(i))
        {
            ucInstanceType = i;
            usInstanceAccTo = 0;
            GetFinishedStat(stUserInstance, ucInstanceType, usInstanceAccTo);
            pstInstanceGrade = stAns.add_grade();
            pstInstanceGrade->set_ins_type(ucInstanceType);

            for (unsigned short j = 1; j <= usInstanceAccTo; ++j)
            {
                unsigned char ucGrade = 0;
                stUserInstance._stInstanceData._astEliteInstanceGrad[i - CInstanceConfigData::INSTANCE_TYPE_ELITE_BEGIN].GetGrad(j, ucGrade);
                pstInstanceGrade->add_data(ucGrade);
            }
        }
    }
    
    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();
    CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
    CMainCtrl::m_pstMain->EncodePBMsg(stAns, CMainCtrl::m_pstMain->m_stEncodeBuf);

    CMainCtrl::m_pstMain->AnswerToClient(stEnpHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
}

/*
void CInstanceMgr::SendInstanceCountLimitToFront(CUserInstance& stUserInstance, CUserTask& stUserTask, PBMsgHead stMsgHead, CEnpNetHead stEnpHead)
{
    MsgAnsInstanceDetail stAns;
    stMsgHead.set_msgid(ID_MAIN_INS_DETAIL_INFO);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
    int iNowTime = CMainCtrl::m_pstMain->m_iNow;

    //精英副本
    unsigned char ucInstanceType = CInstanceConfigData::INSTANCE_TYPE_ELITE;
    unsigned short usInstanceOpenTo = 0;
    GetOpenStat(stUserInstance, stUserTask, ucInstanceType, usInstanceOpenTo);

    if (usInstanceOpenTo !=0)
    {
        MsgInstanceCountLimit* pInstanceCountLimit = stAns.add_count_limit();
        pInstanceCountLimit->set_ins_type(ucInstanceType);

        for (unsigned short i = 1; i <= usInstanceOpenTo; ++i)
        {
            pInstanceCountLimit->add_left_count(stUserInstance._stInstanceData._stEliteAtkStat.IsAtkWin(i, iNowTime) ? 0 : 1);
        }
    }

    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();
    CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
    CMainCtrl::m_pstMain->EncodePBMsg(stAns, CMainCtrl::m_pstMain->m_stEncodeBuf);

    CMainCtrl::m_pstMain->AnswerToClient(stEnpHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
}
*/

void CInstanceMgr::UpdateZoneData()
{
    CZoneData& stZoneData = CMainCtrl::m_pstMain->m_stZoneOnlineData._stZoneData;
    CInstanceZoneData& stInstanceZoneData = stZoneData._stInstanceZoneData;

    //博物馆排行榜数据
    stInstanceZoneData._astMuseumRank.Clear();
    for (int i = 0; i < _stMuseumRank.Size(); ++i)
    {
        stInstanceZoneData._astMuseumRank.AddOneItem(_stMuseumRank[i]);
    }

    CVarObjectKey stKey;
    stKey.m_chDataType = DT_ZONE_DATA;
    stKey.m_u64ID = stZoneData._uiZoneID;
    CMainCtrl::m_pstMain->UpdateData(stKey, stZoneData, VOP_UPDATE);

    return ;
}

void CInstanceMgr::GetSecretInstanceInfo(CUserInstance& stUserInstance, CUserTask& stUserTask, unsigned char ucSecID, char chVipLevel, ::google::protobuf::RepeatedPtrField<MsgSecretInfo>& stSecretInfos)
{
    int iRet = 0;

    //获取等级
    int iIndex = CMainCtrl::m_pstMain->m_stPlayerSnsCommInfoHash.HashFind(stUserTask.GetUserGid());
    if (iIndex < 0)
    {
        CT_ERROR(("%u", stUserTask.GetUserGid()));
        return;
    }
    unsigned short usLevel = CMainCtrl::m_pstMain->m_stPlayerSnsCommInfoHash[iIndex]._usLevel;

    //获取重置次数
    int iMaxResetCount = 0;
    iRet = CMainCtrl::m_pstMain->m_stVipMgr.GetVipDestNum(chVipLevel, VIP_MODULE_ID_19, iMaxResetCount);
    if (RET_OK != iRet)
    {
        CT_ERROR(("%d", iRet));
        return;
    }

    if (ucSecID == 0) //检查所有秘境
    {
        for (unsigned char i = 1; i <= MAX_INSTANCE_SECRET_CONFIG_COUNT; ++i)
        {
            CSecretInstanceConfigData stSecretConfigData;
            iRet = _stSecretInstanceConfig.GetConfig(i, stSecretConfigData);
            if (RET_OK != iRet)
            {
                CT_WARNING(("%d", i));
                continue;
            }

            if (usLevel < stSecretConfigData._usOpenLevel)
            {
                continue;
            }

            MsgSecretInfo* pstMsgSecretInfo = stSecretInfos.Add();
            GetSecDetailInfo(stUserInstance, stUserTask, i, iMaxResetCount, *pstMsgSecretInfo);
        }
    }
    else
    {
        CSecretInstanceConfigData stSecretConfigData;
        iRet = _stSecretInstanceConfig.GetConfig(ucSecID, stSecretConfigData);
        if (RET_OK != iRet)
        {
            CT_WARNING(("%d", ucSecID));
            return;
        }

        MsgSecretInfo* pstMsgSecretInfo = stSecretInfos.Add();
        GetSecDetailInfo(stUserInstance, stUserTask, ucSecID, iMaxResetCount, *pstMsgSecretInfo);

        if (stSecretConfigData._ucHardSecretType != 0)
        {
            MsgSecretInfo* pstMsgSecretInfo = stSecretInfos.Add();
            GetSecDetailInfo(stUserInstance, stUserTask, stSecretConfigData._ucHardSecretType, iMaxResetCount, *pstMsgSecretInfo);
        }
    }
    
}

void CInstanceMgr::GetSecDetailInfo(CUserInstance& stUserInstance, CUserTask& stUserTask, unsigned char ucSecID, int iMaxCanResetCount, MsgSecretInfo& stInfo)
{
    int iRet = 0;

    CSecretInstanceConfigData stSecretConfigData;
    iRet = _stSecretInstanceConfig.GetConfig(ucSecID, stSecretConfigData);
    if (RET_OK != iRet)
    {
        CT_WARNING(("%d", ucSecID));
        return;
    }

    stInfo.set_sec_id(ucSecID);

    //获取评分
    unsigned char ucGrade = 0;
    stUserInstance._stInstanceData._stSecretInstanceData._stGrade.GetGrad((unsigned short)ucSecID, ucGrade);
    stInfo.set_my_grade(ucGrade);

    //获取可以扫荡的副本
    unsigned short usAccInstanceID = 0;
    GetFinishedStat(stUserInstance, stSecretConfigData._ucInstanceType, usAccInstanceID);
    stInfo.set_succ_ins_id(usAccInstanceID);

    //获取当前可以攻打的副本
    unsigned short usOpenInstanceID = 0;
    GetOpenStat(stUserInstance, stUserTask, stSecretConfigData._ucInstanceType, usOpenInstanceID);

    //获取目前已经打到的
    unsigned short usNowAtkWinInstanceID = 
                stUserInstance._stInstanceData._stSecretInstanceData.GetMaxAtkInstanceID(ucSecID, CMainCtrl::m_pstMain->m_iNow);

    if (stSecretConfigData._ucInstanceCount > usNowAtkWinInstanceID) //还没通关
    {
        stInfo.set_is_win(0);

        if (usOpenInstanceID == 0)
        {
            stInfo.set_next_ins_id(0);
        }
        else
        {
            stInfo.set_next_ins_id(usNowAtkWinInstanceID + 1);
        }
        
        stInfo.set_left_ins_count(stSecretConfigData._ucInstanceCount - usNowAtkWinInstanceID);
    }
    else
    {
        stInfo.set_is_win(1);
    }

    //副本详细信息
    for (int i = 1; i <= stSecretConfigData._ucInstanceCount; ++i)
    {
        int iIndex = CMainCtrl::m_pstMain->m_stInstanceZoneDetailInfoHash.HashFind(CInstanceZoneDetailInfo::GetKey(stSecretConfigData._ucInstanceType, i)); //只显示最后一关通关的
        if (iIndex >= 0)
        {
            CInstanceZoneDetailInfo& stInstanceZoneDetailInfo = CMainCtrl::m_pstMain->m_stInstanceZoneDetailInfoHash[iIndex];
            CTSizeString<MAX_VIDEO_KEY_LEN> szVideoToken;
            stInstanceZoneDetailInfo.GetNewKillEnemyVideo(1, szVideoToken);
            stInfo.add_new_video(szVideoToken());

            if (i == stSecretConfigData._ucInstanceCount)
            {
                stInfo.set_first_kill_role_name(stInstanceZoneDetailInfo._szFirstKillRoleName());
                stInfo.set_best_kill_role_name(stInstanceZoneDetailInfo._szBestKillRoleName());
            }
        }
    }

    stInfo.set_ins_count(stSecretConfigData._ucInstanceCount);

    //是否可以重置
    stInfo.set_can_reset_count(iMaxCanResetCount - stUserInstance._stInstanceData._stSecretInstanceData.GetResetCount(ucSecID, CMainCtrl::m_pstMain->m_iNow));
}

bool CInstanceMgr::IsMuseumCanAtk(CUserInstance& stUserInstance)
{
    if (!CInstanceConfigData::IsMuseum(stUserInstance._ucNowAtInstanceType))
    {
        CT_WARNING(("%d", stUserInstance._ucNowAtInstanceType));
        return true;
    }

    unsigned short usAccInstanceID = 0;
    GetFinishedStat(stUserInstance, stUserInstance._ucNowAtInstanceType, usAccInstanceID);

    if (usAccInstanceID >= stUserInstance._usNowAtInstanceID    //副本已通关
        || stUserInstance._usNowAtInstanceID != usAccInstanceID + 1)  //ID不对
    {
        return false;
    }

    CInstanceDetailStatData stDetailStat;
    GetInstanceDetailStat(stUserInstance, stUserInstance._ucNowAtInstanceType, stDetailStat);

    if (stDetailStat.ucNowAccomplishPos >= stUserInstance._usNowPos + 1)    //此怪物已经打过
    {
        return false;
    }

    return true;
}


int CInstanceMgr::DropToGroud(CUserStorage& _stUserGroudBag, CStorageGrid& stStorageGrid, CDropItemData& stDropItemData)
{
    int iRet = 0;
    CItemConfigData stItemConfigData;

    iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetConfig(stDropItemData._ucItemType,
        stDropItemData._usItemConfigID, stItemConfigData);
    CHECK_RETURN(iRet);

    if (0 == stItemConfigData._iUseGrid && false == stItemConfigData._bCanFillInGroundBag)
    {
        CT_ERROR (("%d, %d", stDropItemData._ucItemType, stDropItemData._iItemCount));
        return ERROR_WRONG_ITEM_TYPE;
    }

    CT_TRACE(("%d, %d, %d", stDropItemData._ucItemType, stDropItemData._usItemConfigID, stDropItemData._iItemCount));

    stStorageGrid._stKey._bIsInBag = true;
    stStorageGrid._stKey._ucItemType = stDropItemData._ucItemType;
    stStorageGrid._stKey._uiItemID = stDropItemData._usItemConfigID;
    stStorageGrid._stKey._usStorePos = STORAGE_POS_NOT_OCCUPIED;
    stStorageGrid._shCount = stDropItemData._iItemCount;
    stStorageGrid._iPosValue = stItemConfigData._iPosValue;
    stStorageGrid._shMaxPerGrid = stItemConfigData._shMaxCountPerGrid;

    if (ITEM_TYPE_CLAN_EXP == stDropItemData._ucItemType
        || ITEM_TYPE_CLAN_SILVER == stDropItemData._ucItemType)
    {
        stStorageGrid._iPosValue = stDropItemData._iData1;   //保存家族额外奖励的银币，经验千分比
    }

    _stUserGroudBag.AddGrid(stStorageGrid);

    return 0;
}
